package cn.song.freight.domain.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.Valid;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;

/**
 * 策略配置统一保存请求DTO - V2版本（简化结构）
 * <pre>
 * 根据需求调整，将原有的复杂传参结构简化为嵌套的方式传参，
 * 不再使用临时ID关联数据，采用直接嵌套结构。
 *
 * 调整说明：
 * 1. 将新增、修改、删除的配置数据进行整合，使用一个列表接收
 * 2. 后端只保留列表中的数据，存在ID视为更新，否则视为新增，不存在的视为删除
 * 3. 调整了JSON的层级结构，不再使用临时ID关联数据，而是通过嵌套的方式传参
 * 4. 重量规则直接嵌套在对应的区域配置内
 *
 * 数据处理逻辑：
 * - ID为null：新增操作
 * - ID不为null：更新操作
 * - 数据库中存在但请求中不存在：删除操作
 *
 * @author SongRenShuo
 * @version 2.0.0
 * @since 2025-08-31
 * </pre>
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "策略配置统一保存请求DTO - V2版本（简化结构）")
public class StrategyConfigUnifiedSaveRequestDTO {

    /**
     * 策略ID
     */
    @NotNull(message = "策略ID不能为空")
    @ApiModelProperty(value = "策略ID", required = true, example = "3")
    private Long strategyId;

    /**
     * 区域配置列表
     * 包含所有的区域配置，每个区域包含其对应的重量规则配置列表
     */
    @Valid
    @Size(max = 100, message = "区域配置列表不能超过100条")
    @ApiModelProperty(value = "区域配置列表", required = true)
    private List<AreaConfigDTO> areaConfigList;

    /**
     * 操作人
     */
    @ApiModelProperty(value = "操作人", example = "admin")
    private String operator;

    public String getOperator() {
        return operator == null ? "admin" : operator;
    }


    /**
     * 区域配置DTO
     * 包含区域配置的基本信息和关联的地区ID列表
     */
    @Data
    @ApiModel(description = "区域配置DTO")
    public static class AreaConfigDTO {

        /**
         * 区域配置ID
         * null表示新增，有值表示更新
         */
        @ApiModelProperty(value = "区域配置ID（null表示新增）", example = "5")
        private Long id;

        /**
         * 策略ID
         */
        @NotNull(message = "策略ID不能为空")
        @ApiModelProperty(value = "策略ID", required = true, example = "3")
        private Long strategyId;

        /**
         * 配置名称
         */
        @NotBlank(message = "配置名称不能为空")
        @Size(max = 100, message = "配置名称长度不能超过100个字符")
        @ApiModelProperty(value = "配置名称", required = true, example = "配置名称-3")
        private String name;

        /**
         * 配置描述
         */
        @Size(max = 500, message = "配置描述长度不能超过500个字符")
        @ApiModelProperty(value = "配置描述", example = "默认定价配置")
        private String description;

        /**
         * 首重重量（kg）
         */
        @NotNull(message = "首重重量不能为空")
        @DecimalMin(value = "0", message = "首重重量不能为负数")
        @ApiModelProperty(value = "首重重量（kg）", required = true, example = "0")
        private Double firstWeightKg;

        /**
         * 首重费用（元）
         */
        @NotNull(message = "首重费用不能为空")
        @DecimalMin(value = "0", message = "首重费用不能为负数")
        @ApiModelProperty(value = "首重费用（元）", required = true, example = "0")
        private Double firstWeightFee;

        /**
         * 续重重量（kg）
         */
        @NotNull(message = "续重重量不能为空")
        @DecimalMin(value = "0", message = "续重重量不能为负数")
        @ApiModelProperty(value = "续重重量（kg）", required = true, example = "0")
        private Double additionalWeightKg;

        /**
         * 续重费用（元）
         */
        @NotNull(message = "续重费用不能为空")
        @DecimalMin(value = "0", message = "续重费用不能为负数")
        @ApiModelProperty(value = "续重费用（元）", required = true, example = "0")
        private Double additionalWeightFee;

        /**
         * 抛重比
         */
        @NotNull(message = "抛重比不能为空")
        @DecimalMin(value = "0", message = "抛重比不能为负数")
        @ApiModelProperty(value = "抛重比", required = true, example = "0")
        private Double volumetricWeightRatio;

        /**
         * 选中的地区ID列表
         */
        @NotNull(message = "选中的地区ID列表不能为空")
        @Size(min = 1, max = 1000, message = "选中的地区ID列表长度必须在1-1000之间")
        @ApiModelProperty(value = "选中的地区ID列表", required = true, example = "[19]")
        private List<Long> selectedAreaIds;

        /**
         * 操作人
         */
        @ApiModelProperty(value = "操作人", example = "admin")
        private String operator;

        /**
         * 地区名称列表（只读）
         * 用于前端显示，不参与业务处理
         */
        @ApiModelProperty(value = "地区名称列表（只读）", example = "[\"上海市-上海市-浦东新区\"]")
        private List<String> areaNames;

        /**
         * 重量规则列表
         * 该区域配置对应的所有重量配置
         */
        @Valid
        @Size(max = 100, message = "重量规则列表不能超过100条")
        @ApiModelProperty(value = "重量规则列表", required = true)
        private List<WeightRuleDTO> weightRuleList;
    }

    /**
     * 重量规则DTO
     * 包含重量规则基本信息和其关联的区域配置列表
     */
    @Data
    @ApiModel(description = "重量规则DTO")
    public static class WeightRuleDTO {

        /**
         * 重量规则ID
         * null表示新增，有值表示更新
         */
        @ApiModelProperty(value = "重量规则ID（null表示新增）", example = "2")
        private Long id;

        /**
         * 策略ID
         */
        @NotNull(message = "策略ID不能为空")
        @ApiModelProperty(value = "策略ID", required = true, example = "3")
        private Long strategyId;

        /**
         * 定价配置ID
         * 关联的定价配置ID，可以为null
         */
        @ApiModelProperty(value = "定价配置ID", example = "null")
        private Long pricingId;

        /**
         * 重量上限（kg）
         */
        @NotNull(message = "重量上限不能为空")
        @DecimalMin(value = "0", message = "重量上限不能为负数")
        @ApiModelProperty(value = "重量上限（kg）", required = true, example = "10")
        private Double upperBound;

        /**
         * 区间费用（元）
         */
        @NotNull(message = "区间费用不能为空")
        @DecimalMin(value = "0", message = "区间费用不能为负数")
        @ApiModelProperty(value = "区间费用（元）", required = true, example = "10")
        private Double freight;

        /**
         * 操作人
         */
        @ApiModelProperty(value = "操作人", example = "admin")
        private String operator;


    }

}
